﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_STL_Core.h".
//-------------------------------------------------------------------
/*
	based on code from OpenGL Mathematics (GLM) from http://glm.g-truc.net/
*/

#ifndef _UXS_FAST_MATH_H
#define _UXS_FAST_MATH_H

#pragma once

#include "MathFunc.h"

namespace UX_STL
{
namespace UXMath
{

	//
	// Fast Trigonometry
	//
	
	template <typename T> 
	inline T FSin(const T& x)
	{
		return ( x - ((x * x * x) / T(6)) + ((x * x * x * x * x) /
					T(120)) - ((x * x * x * x * x * x * x) / T(5040)) );
	}
	

	template <typename T> 
	inline T FCos(const T& x)
	{
		return ( T(1) - (x * x * T(0.5)) + (x * x * x * x * T(0.041666666666)) -
					(x * x * x * x * x * x * T(0.00138888888888)) );
	}


	template <typename T> 
	inline T FTan(const T& x)
	{
		return ( x + (x * x * x * T(0.3333333333)) + (x * x * x * x * x * T(0.1333333333333)) +
				(x * x * x * x * x * x * x * T(0.0539682539)) );
	}


	template <typename T> 
	inline T FAsin(const T& x)
	{
		return ( x + (x * x * x * T(0.166666667)) + (x * x * x * x * x * T(0.075)) +
				(x * x * x * x * x * x * x * T(0.0446428571)) +
				(x * x * x * x * x * x * x * x * x * T(0.0303819444)) );
	}
	

	template <typename T> 
	inline T FAcos(const T& x)
	{
		return ( T(1.5707963267948966192313216916398) - FAsin(x) );
	}


	template <typename T> 
	inline T FAtan(const T& y, const T& x)
	{
		return Abs( FAtan(y / x) ) * ( SignOrZero(y) * SignOrZero(x) );
	}


	template <typename T> 
	inline T FAtan(const T& x)
	{
		return ( x - (x * x * x * T(0.333333333333)) + (x * x * x * x * x * T(0.2)) -
				(x * x * x * x * x * x * x * T(0.1428571429)) +
				(x * x * x * x * x * x * x * x * x * T(0.111111111111)) -
				(x * x * x * x * x * x * x * x * x * x * x * T(0.0909090909)) );
	}



	//
	// Fast SQRT
	//
	
	inline float FInvSqrt(const float& x)
	{
		float	tmp		= x;
		float	xhalf	= 0.5f * tmp;
		uint	i		= ReferenceCast<uint>( x );
		i	= 0x5f3759df - (i >> 1);
		tmp	= ReferenceCast<float>( i );
		tmp	= tmp * ( 1.5f - xhalf * tmp * tmp );
		return tmp;
	}


	inline float FSqrt(const float& x)
	{
		return 1.f / FInvSqrt(x);
	}



	//
	// Fast Int Pow ( O(log n) )
	//

	template <typename T>
	inline T FastPowI(T a, T b)
	{
		TypeDescriptor::MustBeInteger<T>();

		T	res = 1;

		while ( b )
		{
			if ( b & 1 )
				res *= a;
			a *= a;
			b >>= 1;
		}
		return res;
	}

//-------------------------------------------------------------------

}	// UXMath
}	// UX_STL

#endif	// _UXS_FAST_MATH_H